package com.wu.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.wu.dao.PaperDao;
import com.wu.pojo.po.paperPo.Answer;
import com.wu.pojo.po.paperPo.Paper;
import com.wu.pojo.po.paperPo.Question;
import com.wu.pojo.dto.*;
import com.wu.pojo.vo.DataVo;
import com.wu.service.AnswerService;
import com.wu.service.PaperService;
import com.wu.service.QuestionService;
import com.wu.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import static com.wu.constants.Constants.*;

@Slf4j
@CacheConfig(cacheNames = "paperDao")
@Service
public class PaperServiceImpl implements PaperService {

    @Autowired
    private PaperDao paperDao;
    @Autowired
    private QuestionService questionService;
    @Autowired
    private CommonUtils commonUtils;
    @Autowired
    private AnswerService answerService;

    @Override
    public List<Paper> queryPaper() {
        return paperDao.queryPaper();
    }

    /**
     * 模糊查询
     */
    @Override
    public List<Paper> fuzzyQuery(Paper paperInfo) {
        return paperDao.fuzzyQuery(paperInfo);
    }

    @Cacheable
    @Override
    public List<Paper> queryPaperByUserID(String userId) {
        return paperDao.queryPaperByUserID(userId);
    }

    @Override
    public List<Paper> queryPaperWithStatus1() {
        return paperDao.queryPaperWithStatus1();
    }

    @Cacheable
    @Override
    public Paper queryPaperByID(String id) {
        return paperDao.queryPaperByID(id);
    }

    @Transactional
    @Override
    @CacheEvict(value ="paperDao", allEntries = true)
    public boolean insertPaper(Paper paper) {
        if (paper != null && !"".equals(paper.getPaperId())) {
            try {
                // System.err.println(paper.toString());
                int i = paperDao.insertPaper(paper);
                if (i == 1) {
                    return true;
                } else {
                    throw new RuntimeException("a:插入试卷失败！" + paper);
                }
            } catch (Exception e) {
                throw new RuntimeException("b:插入试卷失败：" + e.getMessage());
            }
        } else {
            throw new RuntimeException("c:插入试卷失败，Paper的id不能为空！");
        }
    }

    /**
     * 单条更新
     */
    @CacheEvict(value ="paperDao", allEntries = true)
    @Transactional
    @Override
    public boolean updatePaper(Paper paper) {
        if (paper != null && !"".equals(paper.getPaperId())) {
            try {
                int i = paperDao.updatePaper(paper);
                if (i == 1) {
                    return true;
                } else {
                    throw new RuntimeException("a:修改试卷失败！" + paper);
                }
            } catch (Exception e) {
                throw new RuntimeException("b:修改试卷失败：" + e.getMessage());
            }
        } else {
            throw new RuntimeException("c:修改试卷失败，Paper的id不能为空！");
        }
    }

    /**
     * 批量更新
     */
    @CacheEvict(value ="paperDao", allEntries = true)
    @Transactional
    @Override
    public boolean updatePapers(List<String> paperIds, String status) {

        for (String paperId : paperIds) {// 批量更新状态
            try {
                paperDao.updatePaper(new Paper().setPaperId(paperId).setStatus(status));
            } catch (Exception e) {
                log.error("问卷ID：{}，更新失败：" + paperId);
                throw new RuntimeException("问卷ID：{}，更新失败：" + paperId);
            }
        }
        return true;
    }

    /**
     * 单条删除
     */
    @CacheEvict(value ="paperDao", allEntries = true)
    @Transactional
    @Override
    public boolean deletePaper(String id) {
        if (id != null && !"".equals(id)) {
            try {
                // System.out.println(id);
                int i = paperDao.deletePaper(id);
                if (i == 1) {
                    return true;
                } else {
                    throw new RuntimeException("a:删除试卷失败！" + id);
                }
            } catch (Exception e) {
                throw new RuntimeException("b:删除试卷失败：" + e.getMessage());
            }
        } else {
            throw new RuntimeException("c:删除试卷失败，Paper的id不能为空！");
        }
    }

    /**
     * 批量删除
     */
    @CacheEvict(value ="paperDao", allEntries = true)
    @Transactional
    @Override
    public boolean deleteManyPapers(PaperDeleteDTO paperDeleteDTO) {

        // 判断删除标志
        if (DELETE.equals(paperDeleteDTO.getFlag())) {// 彻底删除
            for (String paperId : paperDeleteDTO.getPaperIds()) {
                if (answerService.queryAnswerByPaperId(paperId).size() > 0) {
                    answerService.deleteAnswerByPaperId(paperId);// 删除答案
                }
                if (questionService.queryQuestionByPaperId(paperId).size() > 0) {
                    questionService.deleteQuestionsByPaperId(paperId);// 删除题目
                }
                paperDao.deletePaper(paperId);// 删除问卷
            }
            return true;
        }

        // 否则是普通删除
        for (String paperId : paperDeleteDTO.getPaperIds()) {
            Paper paper = queryPaperByID(paperId);
            paper.setStatus(STATUS_DELETE);// 更改问卷状态为废弃
            updatePaper(paper);
        }
        return true;
    }

    /**
     * 批量粉碎
     */
    @CacheEvict(value ="paperDao", allEntries = true)
    @Transactional
    @Override
    public boolean deleteAll() {
        List<Paper> paperList = paperDao.fuzzyQuery(new Paper().setStatus("3"));// 获取回收站paperId列表
        for (Paper paper : paperList) {
            if (null != answerService.queryAnswerByPaperId(paper.getPaperId()) && answerService.queryAnswerByPaperId(paper.getPaperId()).size() > 0) {
                answerService.deleteAnswerByPaperId(paper.getPaperId());// 删除答案
            }
            if (null != questionService.queryQuestionByPaperId(paper.getPaperId()) && questionService.queryQuestionByPaperId(paper.getPaperId()).size() > 0) {
                questionService.deleteQuestionsByPaperId(paper.getPaperId());// 删除题目
            }
        }
        paperDao.deletePaperByStatus();// 删除问卷
        return true;
    }

    /**
     * 批量还原
     */
    @CacheEvict(value ="paperDao", allEntries = true)
    @Transactional
    @Override
    public boolean resManyPapers(PaperDeleteDTO paperDeleteDTO) {
        for (String paperId : paperDeleteDTO.getPaperIds()) {
            Paper paper = queryPaperByID(paperId);
            paper.setStatus(STATUS_UNRELEASE);// 更改问卷状态为未发布状态
            updatePaper(paper);
        }
        return true;
    }

    /**
     * 处理Paper的data，获取问卷数据（核心逻辑）
     */
    @Override
    public Object getQuestionData(String paperId, String userId, String remark) throws Exception {

        // 1、查询问卷,获取问卷列表
        Paper paper = queryPaperByID(paperId);
        if (paper == null) {
            return null;
        }

        // 2、获取基础数据
        List<Question> questions = questionService.queryQuestionByPaperId(paper.getPaperId());// 问题列表
        int totalCount = getPaperCount(paper.getPaperId());// 问卷参与人数

        // 3、获取问题数据
        JSONArray jsonArray = new JSONArray();// JSON数组，装载question数据
        int indicator = 0;// 设置计分器

        for (Question question : questions) {// 遍历问题列表

            // 1.参数验证
            if (question.getQuestionType() == null || "".equals(question.getQuestionType())) {
                throw new RuntimeException("问题类型异常");
            }

            // 2.参数整理
            // 获取选项数组、转换为String数组，方便后续回答和选项作对比
            Object[] o = JSONArray.fromObject(question.getQuestionOption()).toArray();
            String[] options = new String[o.length];
            for (int i = 0, n = o.length; i < n; i++) {// 获取选项列表
                options[i] = o[i].toString();
            }

            int[] ansCount = new int[options.length];// 定义答案统计数组，长度是对应问题选项的长度
            int[] percent = null;// 定义答案统计占比
            List<String> answerContents = new ArrayList<>();// 定义答案内容，问答题需要

            // 3、整合问卷数据
            // 查询用户答题记录
            JSONObject jPaper = new JSONObject();
            String answerContent = null;

            Answer answer = answerService.queryAnswerByPaperIdAndUserIdAndQuestionId(paper.getPaperId(), userId, question.getId());
            if (null == answer) { // 无答题记录，遍历问卷，将答案设为空
                List<Answer> answerList = null;
                if (userId == null) { //管理员查看问卷
                    answerList = answerService.queryAnswerByPaperId(paper.getPaperId());
                } else { // 用户查看问卷
                    answerList = answerService.queryAnswerByPaperIdAndUserId(paper.getPaperId(), userId);
                }
                for (Answer answer1 : answerList) {
                    // 遍历答案,记录answerContent
                    if (answer1.getAnswerContents().length() < 4) {
                        continue;// 答案内容为空,跳过
                    }
                    // 获取回答内容，去数组框[""]
                    answerContent = answer1.getAnswerContents().substring(2, answer1.getAnswerContents().length() - 2);

                    // 单选题
                    if (RADIO.equals(question.getQuestionType())) {
                        // 遍历选项
                        for (int i = 0, n = options.length; i < n; i++) {
                            // 比对答案
                            if (answerContent.length() > 0) {
                                if (answerContent.equals(options[i])) {
                                    // 满足条件-累加答案统计数组
                                    ansCount[i]++;
                                    // 积分器: A-1分，B-2分，C-3分
                                    indicator += 7 * (i + 1);
                                }
                            }
                        }
                        jPaper.put("answerContents", answerContent);
                    }

                    // 多选题
                    else if (MULTIPLE.equals(question.getQuestionType())) {
                        String[] multipleAnswer = answerContent.split("\",\"");// 将剪切后的答案分割为数组
                        for (int i = 0, n = options.length; i < n; i++) {// 遍历options选项列表
                            for (int j = 0, m = multipleAnswer.length; j < m; j++) {// 遍历答案列表比对答案
                                if (multipleAnswer.length >= 1) {
                                    if (multipleAnswer[j].equals(options[i])) {
                                        answerContents.add(multipleAnswer[j]);// 放入答案
                                        ansCount[i]++;// 答案相同 次数+1
                                        // 积分器: A-1分，B-2分，C-3分
                                        indicator += 7 * (i + 1);
                                    }
                                }
                            }
                        }
                        jPaper.put("answerContents", answerContents);
                    }

                    // 问答题
                    else if (COMPLETION.equals(question.getQuestionType())) {
                        jPaper.put("answerContents", answerContents);
                    }
                }
            } else { //有答题记录，遍历问卷，将答案返回
                if (answer.getAnswerContents().length() < 4) {
                    continue;// 答案内容为空,跳过
                }
                // 获取回答内容，去数组框[""]
                answerContent = answer.getAnswerContents().substring(2, answer.getAnswerContents().length() - 2);

                // 单选题
                if (RADIO.equals(question.getQuestionType())) {
                    // 遍历选项
                    for (int i = 0, n = options.length; i < n; i++) {
                        // 比对答案
                        if (answerContent.length() > 0) {
                            if (answerContent.equals(options[i])) {
                                // 满足条件-累加答案统计数组
                                ansCount[i]++;
                                // 积分器: A-1分，B-2分，C-3分
                                indicator += 7 * (i + 1);
                            }
                        }
                    }
                    jPaper.put("answerContents", answerContent);// 单选题答案返显
                }

                // 多选题
                else if (MULTIPLE.equals(question.getQuestionType())) {
                    String[] multipleAnswer = answerContent.split("\",\"");// 将剪切后的答案分割为数组
                    for (int i = 0, n = options.length; i < n; i++) {// 遍历options选项列表
                        for (int j = 0, m = multipleAnswer.length; j < m; j++) {// 遍历答案列表比对答案
                            if (multipleAnswer.length >= 1) {
                                if (multipleAnswer[j].equals(options[i])) {
                                    answerContents.add(multipleAnswer[j]);// 放入答案
                                    ansCount[i]++;// 答案相同 次数+1
                                    // 积分器: A-1分，B-2分，C-3分
                                    indicator += 7 * (i + 1);
                                }
                            }
                        }
                    }
                    jPaper.put("answerContents", answerContents);// 填空题答案内容
                }

                // 问答题
                else if (COMPLETION.equals(question.getQuestionType())) {
                    if (answerContent.length() > 0) {
                        answerContents.add(answerContent);// 把问题答案放入list
                    }
                    jPaper.put("answerContents", answerContents);// 问题题答案返显
                }
            }

            // 计算选项占比
            percent = this.getPercent(ansCount);

            // 4.组装问题参数
            JSONArray optionArray = JSONArray.fromObject(options);// 问题选项数组转换为JSON数组
            JSONArray jTimes = JSONArray.fromObject(ansCount);// 次数数组转化为JSON数组
            JSONArray jPercent = JSONArray.fromObject(percent);

            if (answerContents.isEmpty() && (null == answerContent || "".equals(answerContent))) {
                jPaper.put("answerContents", answerContents);// 排除单选题，必传字段 否则多选框无法选择
            }

            jPaper.put("questionId", question.getId());
            jPaper.put("questionNo", question.getQuestionNo());// 问题序号
            jPaper.put("questionType", question.getQuestionType());
            jPaper.put("questionTitle", question.getQuestionTitle());
            jPaper.put("questionOption", optionArray);// 选项内容
            jPaper.put("answerContentTimes", jTimes);// 选项被选次数
            jPaper.put("percent", jPercent);// 选项占比
            jsonArray.add(jPaper);
        }
        // 取平均 总分值/参与人数 = 平均分值
        if (totalCount != 0) {
            indicator = indicator / totalCount;
        }

        // 4、组装问卷参数
        JSONObject dataJson = new JSONObject();
        dataJson.put("paperId", paper.getPaperId());
        dataJson.put("title", paper.getTitle());// 标题
        dataJson.put("descri", paper.getDescri());// 问卷描述
        dataJson.put("status", paper.getStatus());
        dataJson.put("createTime", commonUtils.getLongByDate(paper.getCreateTime()));
        dataJson.put("startTime", commonUtils.getDateStringByDate(paper.getStartTime()));
        dataJson.put("endTime", commonUtils.getDateStringByDate(paper.getEndTime()));
        dataJson.put("totalCount", totalCount);
        dataJson.put("questions", jsonArray);
        dataJson.put("indicator", indicator);// 得分

        return dataJson;// 最后返回对象
    }

    /**
     * 根据paperId、userId获取该问卷分值
     */
    @Override
    public int getDataProcess(String paperId, String remark) {

        // 1、查询问卷,获取问卷列表
        Paper paper = queryPaperByID(paperId);
        if (paper == null) {
            return 0;
        }

        // 2、获取基础数据
        List<Question> questions = questionService.queryQuestionByPaperId(paper.getPaperId());// 问题列表

        // 3、获取问题数据
        int indicator = 0;// 计分器
        for (Question question : questions) {// 遍历问题列表

            // 1.参数验证
            if (question.getQuestionType() == null || "".equals(question.getQuestionType())) {
                throw new RuntimeException("问题类型异常");
            }

            // 2.参数整理
            // 获取选项数组、转换为String数组，方便后续回答和选项作对比
            Object[] o = JSONArray.fromObject(question.getQuestionOption()).toArray();
            String[] options = new String[o.length];
            for (int i = 0, n = o.length; i < n; i++) {// 获取选项列表
                options[i] = o[i].toString();
            }

            // 3.整合问卷数据
            List<Answer> answerList = answerService.queryAnswerByRemark(question.getId(), remark);// 根据userId查询答案列表
            String answerContent = null;
            for (Answer answer : answerList) {// 遍历答案,记录answerContent

                if (answer.getAnswerContents().length() < 4) {
                    continue;// 答案内容为空,跳过
                }
                answerContent = answer.getAnswerContents().substring(2, answer.getAnswerContents().length() - 2);// 获取回答内容，去数组框[""]}

                // 单选题
                if (RADIO.equals(question.getQuestionType())) {
                    // 遍历选项
                    for (int i = 0, n = options.length; i < n; i++) {
                        // 比对答案
                        if (answerContent.length() > 0) {
                            if (answerContent.equals(options[i])) {
                                // 积分器: A-1分，B-2分，C-3分
                                indicator += 7 * (i + 1);
                            }
                        }
                    }
                }

                // 多选题
                else if (MULTIPLE.equals(question.getQuestionType())) {
                    String[] multipleAnswer = answerContent.split("\",\"");// 将剪切后的答案分割为数组
                    for (int i = 0, n = options.length; i < n; i++) {// 遍历options选项列表
                        for (int j = 0, m = multipleAnswer.length; j < m; j++) {// 遍历答案列表比对答案
                            if (multipleAnswer.length >= 1) {
                                if (multipleAnswer[j].equals(options[i])) {
                                    // 积分器: A-7分，B-14分，C-21分
                                    indicator += 7 * (i + 1);
                                }
                            }
                        }
                    }
                }

                // 问答题
                else if (COMPLETION.equals(question.getQuestionType())) {
                    if (answerContent.length() > 0) {
                        // 计算公式
                    }
                }
            }
        }

        return indicator;
    }

    @Transactional
    @Override
    @CacheEvict(value ="paperDao", allEntries = true)
    public boolean updatePaperQuestions(PaperUpdateDTO paper, String userId, PaperAddDTO paperAddDTO){
        deletePaper(paper.getPaperId());
        questionService.deleteQuestionsByPaperId(paper.getPaperId());
        return true;
    }

    /**
     * 查询参与人数
     */
    @Override
    public int getPaperCount(String paperId) {
        List<Question> questions = questionService.queryQuestionByPaperId(paperId);// 问题列表
        // 问卷参与人数 ==>第一题回答次数
        return (questions.isEmpty()) ? 0 : answerService.countAnswer(paperId, questions.get(0).getId());
    }

    /**
     * 根据paperId、userId获取该问卷分值
     */
    @Override
    public List<DataVo> scoreCollect(DataVo dataVo) {
        return paperDao.scoreCollect(dataVo);
    }

    @Override
    public String getExcelPath(String paperId) {
        return paperDao.getExcelPath(paperId);
    }

    /**
     * 各答案占比算法
     */
    private int[] getPercent(int[] ansCount) {

        int total = 0;// 总数
        for (int h = 0; h < ansCount.length; h++) {
            total += ansCount[h];
        }
        int[] percent = new int[ansCount.length];// 长度为选项个数
        if (total != 0) {
            for (int k = 0; k < ansCount.length; k++) {// 计算每个选项占比
                percent[k] = ansCount[k] * 100 / total;
            }
        }
        return percent;
    }
}


